iT邦幫忙

2023 iThome 鐵人賽

DAY 9
0

前面花了不少篇幅講 FP,今天要拉回來講前端技術 - Component Testing (元件測試)。

為甚麼要寫元件測試?

說起元件測試,雖然我知道這東西好一陣子了,也嘗試使用過 React Testing Library,但實際寫專案就是會懶得寫,心裡總是想著 UI 就瀏覽器開著邊寫邊看就好啦有 E2E 和 unit test,很穩了。直到最近被我們大老闆抓到沒寫,被念閒聊一波之後才重新拾起一個重要觀念

容易測試的元件才是好元件

為甚麼要用 Cypress 寫元件測試?

cypress 一開始是 end-to-end (點對點) 測試工具,大約2021年開始釋出元件測試功能,經過兩年發展目前看起來已經越來越成熟好用。真正讓我決定使用 Cypress 是看完這篇評比 Cypress Component Testing vs React Testing Library - the complete comparison。看起來 Cypress 語法比較簡潔、效能不錯、介面友善,而且在有使用 Cypress 做為 e2e 工具的情況下,不需要額外安裝好幾套工具,也更方便統計測試覆蓋率。

安裝測試工具

https://ithelp.ithome.com.tw/upload/images/20230924/20158615M7Xr3nVifo.png

  1. 安裝 cypress

    npm i -D cypress
    
  2. 修改 package.json

    "scripts": {
    ...
    "cy:e2e": "cypress run --e2e",
    "cy:component": "cypress run --component",
    "cy:open": "cypress open"
    },
    
  3. 執行 npm run cy:open,選擇 component testing
    https://ithelp.ithome.com.tw/upload/images/20230924/2015861594YoAwsTEq.png

  4. 這時候應該會看到它已經自動偵測到我們是 Next.js 專案,並且提供一些預設設定檔案,這邊都一律下一步
    https://ithelp.ithome.com.tw/upload/images/20230924/20158615dtVoaEvpzI.png
    https://ithelp.ithome.com.tw/upload/images/20230924/20158615f8srEmJHh2.png
    https://ithelp.ithome.com.tw/upload/images/20230924/201586151Up7EZZ0Eh.png

  5. 如果出現錯誤,只要修改 tsconfig,把 "moduleResolution": "bundler" 改成 "moduleResolution": "node" https://ithelp.ithome.com.tw/upload/images/20230924/2015861535i7bmPQ9n.png

  6. 到最後看到瀏覽器選單就表示安裝成功囉 !
    https://ithelp.ithome.com.tw/upload/images/20230924/20158615HhkkHYRwwR.png

新增測試模板

cypress 很貼心的提供了根據現有元件自動建立測試模板的功能。以我們 TDD 流程來說,只要先寫一個空的 Component,然後滑鼠點點點,測試模板就自動生成了。

https://ithelp.ithome.com.tw/upload/images/20230924/20158615HpKufelvgI.png
https://ithelp.ithome.com.tw/upload/images/20230924/201586153FFtXddoJc.png
https://ithelp.ithome.com.tw/upload/images/20230924/20158615vOR8wEfqlt.png

外觀看起來一開始會有點怪怪的,這是因為我們還沒有做 css 設定

https://ithelp.ithome.com.tw/upload/images/20230924/20158615MpOVjdLZ50.png

https://ithelp.ithome.com.tw/upload/images/20230924/20158615jyUA2zKrZD.png

import '../../src/app/globals.css'

只要在 component.ts 進行以上設定即可看到套用好的外觀元件

https://ithelp.ithome.com.tw/upload/images/20230924/20158615z5sjh0rgNQ.png

開始撰寫測試

程式碼請參考 D09/component-test

初始化元件

const Initializer = () => {
  const setCourseName = useSetAtom(courseNameAtom)
  useEffect(() => {
    setCourseName(initialCourseName) // 3. 重置 atom
  }, [])

  return <></>
}

describe('<CourseName />', () => {
  beforeEach(() => {
    ReactDom.unmountComponentAtNode(getContainerEl()) // 1. 清空所有掛載的元件
    cy.mount(<Initializer />) // 2. 掛載初始化元件
    cy.mount(<CourseName />) // 4. 掛載受測元件
  })
})

Atom 會把各種狀態儲存在 React 的 context 裡面,導致我們難以透過 stub 等方式去做一個假的 atom。為了解決這個問題,我們要藉由建立一個初始化元件,在每次元件被掛載上去的時候,觸發 atom 的初始化。

還記得 AAA 嗎? 這邊做的就是 Arange

撰寫元件測試

  it('should not show error message and have empty input in the beginning', () => {
    // assert
    cy.get('input').should('have.value', '')
    cy.get('.error-message').should('not.exist')
  })
  it('should not show error message on blur when input is invalid', () => {
    // assert
    cy.get('input').type('He110 w0r1d')
    cy.get('.error-message').should('not.exist')
  })
  it('should show error message on blur when input is invalid', () => {
    // act
    cy.get('input').clear().focus().blur()
    // assert
    cy.get('.error-message')
  })
  it('should show error message on change when input is invalid', () => {
    // act
    cy.get('input').type('1{backspace}')
    // assert
    cy.get('.error-message')
  })

https://ithelp.ithome.com.tw/upload/images/20230924/20158615MUgjlwTwdq.png


一開始肯定全部失敗,因為我們連 atom 都還沒有準備,明天我們再來看看該怎麼通過所有檢查


上一篇
D08 - 資料型別盒子
下一篇
D10 - 通過元件測試
系列文
從 Next.js 開始的 Functional Programming30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言